<template>
  <a-spin :spinning="spinning">
    <a-row
      :gutter="24"
      class="mb10 aic"
      type="flex"
      style="margin-left: 0; margin-right: 0"
    >
      <div v-if="showSelection" class="dib fs12">
        已选择
        <span class="color-1989fa">{{
          selectedRowKeys.length || selectRowKeys.length
        }}</span
        >条数据
        <a-button type="link" size="small" @click="onCancelSelect">
          取消选择
        </a-button>
      </div>
      <a-col flex="1">
        <slot name="btns" />
      </a-col>

      <a-button v-if="hasExport" size="small" class="mr10" @click="exportExcel">
        导出
      </a-button>
      <a-button v-if="hasRefresh" size="small" class="mr10" @click="refresh">
        刷新
      </a-button>
      <a-button v-if="hasReset" size="small" class="mr10" @click="reset">
        重置
      </a-button>
      <column-settings
        v-if="showSetting && !columns.length"
        v-model="menuListFields"
        class="show-setting"
        :button-style="buttonStyle"
        :menu-name="menuName"
        @change="refreshColumn"
      />
    </a-row>
    <a-table
      ref="tableDom"
      v-dragWidth="{ columns: tableColumns, id: `remoteTable${uid}` }"
      bordered
      :uid="uid"
      :loading="false"
      :columns="tableColumns"
      class="myRemoteTable"
      :class="{
        tableEmpty: tableDatas.length === 0
      }"
      :data-source="tableDatas"
      :pagination="false"
      :scroll="{
        x: x || '100%',
        y: isCalcTableHeight ? yy : scrollY
      }"
      :row-selection="myRowSelection"
      :row-key="rowKey"
    >
      <!-- 自定义过滤器 -->
      <div
        v-for="(item, columnIndex) in tableColumns"
        :slot="item.scopedSlots && item.scopedSlots.filterDropdown"
        :key="item.scopedSlots && item.scopedSlots.filterDropdown"
        slot-scope="{ confirm, clearFilters, column }"
        class="p10"
      >
        <!-- 批量搜索 -->
        <template v-if="item.isBatch">
          <div class="rm-popover pr p10">
            <h4 class="mb10">批量查询</h4>
            <a-input
              v-model="item.batchValue"
              style="width: 100%"
              allow-clear
              placeholder="支持复制或输入关键词"
              @pressEnter="e => handlerBatchBlur(e, columnIndex)"
              @blur="e => handlerBatchBlur(e, columnIndex)"
            />
            <a-tag
              v-for="(t, tIndex) in item.batchTags"
              :key="t"
              style="float: left"
              closable
              class="mb10"
              @close="handlerDelBatchItem(tIndex, columnIndex)"
            >
              {{ t }}
            </a-tag>
          </div>
          <a-row class="action-wrap p10 df jcfe">
            <a-button
              size="small"
              class="mr10"
              @click="changeBatchMode(columnIndex, false)"
            >
              切换普通查询
            </a-button>
            <a-button
              size="small"
              class="mr10"
              type="primary"
              ghost
              @click="
                () => {
                  item.batchTags = []
                  handleBatchSearch(confirm, column, true)
                }
              "
            >
              重置
            </a-button>
            <a-button
              size="small"
              type="primary"
              @click="
                () => {
                  handleBatchSearch(confirm, column, true)
                }
              "
            >
              确定
            </a-button>
          </a-row>
        </template>
        <template v-else>
          <div class="sort-wrap df jcsb mb10">
            <div>
              <span
                class="cp mr20"
                :style="{
                  color: item.desc === 'asc' ? '#1989fa' : ''
                }"
                @click="handleSort('asc', columnIndex, confirm)"
              >
                <a-icon type="sort-ascending" />
                <span class="fs12">升序</span>
              </span>
              <span
                class="cp"
                :style="{
                  color: item.desc === 'desc' ? '#1989fa' : ''
                }"
                @click="handleSort('desc', columnIndex, confirm)"
              >
                <a-icon type="sort-descending" />
                <span class="fs12">降序 </span>
              </span>
            </div>
            <div>
              <a-checkbox
                v-if="item.needEmpty"
                :key="item.isBlank"
                :checked="item.isBlank"
                @change="e => setBlank(e, columnIndex)"
              >
                空
              </a-checkbox>
              <a-icon
                v-if="item.isBatchQuery == 1"
                type="diff"
                :style="{
                  color: item.batchTags?.length > 0 ? '#1989fa' : ''
                }"
                style="font-size: 20px; margin-left: 6px"
                @click="changeBatchMode(columnIndex, true)"
              />
            </div>
          </div>
          <div v-if="item.model === 1" class="date-wrap mb10">
            <a-range-picker
              v-model="item.filterValue"
              style="width: 300px"
              format="YYYY-MM-DD"
              value-format="YYYY-MM-DD"
            />
          </div>
          <!-- 数字范围 model 7-->
          <div
            v-else-if="item.model === 7"
            class="number-wrap mb10 pr10 pl10 df aic jcc"
            style="width: 250px"
          >
            <a-input-number
              :min="0"
              placeholder="最小值"
              :precision="0"
              allow-clear
              v-model="item.filterValue[0]"
              class="mr10 f1"
            />
            ~
            <a-input-number
              :min="item.filterValue[0] || 0"
              :precision="0"
              allow-clear
              placeholder="最大值"
              v-model="item.filterValue[1]"
              class="ml10 f1"
            />
          </div>
          <div v-else class="search-wrap mb10">
            <!-- 远程搜索 -->
            <a-input-search
              v-if="item.model === 2"
              v-model="item.params.queryStr"
              :placeholder="`搜索 ${column.title}`"
              :loading="loading"
              @change="e => remoteSearch(e, columnIndex)"
            />
            <a-input
              v-else
              v-model="item.searchValue"
              :placeholder="`搜索 ${column.title}`"
              @change="e => inputSearch(e, columnIndex)"
              @pressEnter="() => handleSearch(confirm, column)"
            />
            <div class="checkbox-wrap">
              <a-spin :spinning="loading">
                <a-checkbox
                  :key="item.checkAll"
                  :checked="item.checkAll"
                  :indeterminate="item.indeterminate"
                  @change="e => onCheckAllChange(e, columnIndex)"
                >
                  全选
                </a-checkbox>
                <span v-if="item.plainOptions"
                  >({{ item.filterValue ? item.filterValue.length : 0 }}/
                  {{ item.plainOptions && item.plainOptions.length }})</span
                >
                <a-divider
                  dashed
                  style="margin-top: 10px; margin-bottom: 10px"
                />
                <a-checkbox-group
                  v-model="item.filterValue"
                  style="
                    min-height: 40px;
                    max-height: 200px;
                    overflow: auto;
                    max-width: 300px;
                    min-width: 200px;
                  "
                  @change="values => onChange(values, columnIndex)"
                >
                  <div v-for="c in item.plainOptions" :key="c.value">
                    <a-checkbox :value="c.key" :label="c.key">
                      {{ c.value || '空' }}
                    </a-checkbox>
                  </div>
                </a-checkbox-group>
              </a-spin>
            </div>
          </div>

          <div class="action-wrap df jcfe">
            <a-button
              type="primary"
              icon="search"
              size="small"
              style="width: 90px; margin-right: 8px"
              @click="() => handleSearch(confirm, column)"
            >
              搜索
            </a-button>
            <a-button
              size="small"
              style="width: 90px"
              @click="() => handleReset(confirm, columnIndex, clearFilters)"
            >
              重置
            </a-button>
          </div>
        </template>
      </div>
      <!-- 自定义表头 -->

      <span
        :slot="item.slots.title"
        :key="item.key"
        v-for="item in customTitleColumns"
      >
        <slot :name="item.slots.title">
          {{ item.title }}
        </slot>
      </span>

      <span
        v-for="item in tableColumns"
        :slot="(item.scopedSlots && item.scopedSlots?.customRender) || item.key"
        :key="item.key"
        slot-scope="text, record, $index"
      >
        <slot
          v-if="item.scopedSlots && item.scopedSlots.customRender"
          :record="record"
          :text="text"
          :index="$index"
          :name="item?.scopedSlots.customRender"
        >
          {{ record[item.dataIndex] }}
        </slot>
      </span>
    </a-table>
    <!-- 分页 -->
    <div
      v-if="hasPaginate"
      ref="pagination"
      class="df jcsb p10"
      style="padding-bottom: 0"
    >
      <div class="o06">
        {{
          `共 ${total || 0}条数据，第${pageNum}/${Math.ceil(
            (total || 0) / pageSize
          )}页`
        }}
      </div>
      <div>
        <a-pagination
          v-model="pageNum"
          size="small"
          :page-size="pageSize"
          :total="total"
          :page-size-options="['20', '50', '100', '150', '200']"
          show-size-changer
          show-quick-jumper
          @change="changePage"
          @showSizeChange="changePage"
        />
      </div>
    </div>
  </a-spin>
</template>
<script>
// import { Table } from 'ant-design-vue'
import { debounce } from 'lodash'
import columnSettings from './columnSettings.vue'
import { config_list_menu_field_post_ } from 'server/apis/1890.js'
import {
  executeServer,
  getConfigColumn,
  executeSearch,
  useColumnWidth
} from './remoteTable.js'
import { observeDomResize } from 'utils/index.js'
export default {
  components: {
    columnSettings
  },
  props: {
    columns: {
      type: Array,
      default: () => {
        return []
      }
    },
    value: {
      type: Array,
      default: () => {
        return []
      }
    },
    queryParams: {
      type: Object,
      default: () => {
        return {}
      }
    },
    // 获取列接口的菜单名称
    menuName: {
      type: String,
      default: ''
    },
    // 是否支持多选
    showSelection: {
      type: Boolean,
      default: true
    },
    interfaceURL: {
      type: String,
      default: ''
    },
    // 是否显示列设置
    showSetting: {
      type: Boolean,
      default: false
    },
    hasExport: {
      type: Boolean,
      default: false
    },
    hasRefresh: {
      type: Boolean,
      default: true
    },
    // 表格是否显示分页
    hasPaginate: {
      type: Boolean,
      default: true
    },
    // 是否显示操作项目
    hasReset: {
      type: Boolean,
      default: true
    },
    // 是否显示操作项目
    hasAction: {
      type: Boolean,
      default: false
    },
    // 列设置的按钮样式
    buttonStyle: {
      type: Object,
      default: () => {
        return {}
      }
    },
    // 列宽设置
    columnWidth: {
      type: Object,
      default: () => {
        return {}
      }
    },
    columnFixed: {
      type: Object,
      default: () => {
        return {}
      }
    },
    x: {
      type: [String, Number],
      default: '100%'
    },
    y: {
      type: [String, Number],
      default: 600
    },
    sy: {
      type: [String, Number],
      default: 0
    },
    // 拉取table数据的接口参数
    apiParams: {
      type: Object,
      default: () => {
        return {}
      }
    },
    rowKey: {
      type: [Function, String],
      default: (r, index) => r.id || index
    },
    // 列设置的参数
    queryFields: {
      type: Array,
      default: () => {
        return []
      }
    },
    rowType: {
      type: String,
      default: 'checkbox'
    },
    selectRowKeys: {
      type: Array,
      default: () => {
        return []
      }
    },
    callback: {
      type: Function,
      default: null
    },
    // 接口响应后function
    afterRespLoad: {
      type: Function,
      default: null
    },
    // 表格高度是否自动计算
    isCalcTableHeight: {
      type: Boolean,
      default: false
    }
  },
  data() {
    return {
      scrollX: 0,
      tableDatas: [],
      options: [],
      tableColumns: [],
      query: {
        sortList: [],
        ...this.queryParams
      },
      uid: 0,
      loading: false,
      pageNum: 1,
      pageSize: 50,
      spinning: false,
      total: 0,
      localApiParams: {},
      menuListFields: [],
      selectedRowKeys: [],
      selectedRows: [],
      currentPageRowKeys: {},
      pageRows: {},
      isScrolled: false,
      yy: 780
    }
  },
  computed: {
    customTitleColumns() {
      return this.tableColumns.filter(s => s.slots)
    },
    scrollY() {
      const mql = window.matchMedia('(max-width: 1400px)')
      if (mql.matches) {
        return this.sy || 700
      }
      return this.y
    },
    myRowSelection() {
      const { pageNum, rowType } = this
      if (this.showSelection) {
        const selectedRowKeys =
          this.currentPageRowKeys[pageNum] || this.selectRowKeys
        return {
          selectedRowKeys,
          type: rowType,
          onChange: this.onSelectChange,
          onSelect: this.onSelect,
          fixed: true
        }
      }
      return null
    }
  },
  watch: {
    value: {
      handler(val) {
        this.tableDatas = val || []
      },
      immediate: true,
      deep: true
    },
    tableDatas: {
      handler(val) {
        if (this.tableDatas.length === 0) {
          // setTimeout(() => {
          //   const target = this.$refs.tableDom.$el.querySelector('.ant-table-header')
          //   target.scrollLeft = this.scrollX
          // }, 500)
        }
        this.$emit('input', val)
      },
      immediate: true,
      deep: true
    },
    columns: {
      handler(val) {
        val && this.createColumns(val)
      },
      immediate: true,
      deep: true
    },
    queryParams: {
      handler(val, oldValue) {
        if (JSON.stringify(val) !== JSON.stringify(oldValue)) {
          this.query = {
            ...this.query,
            ...val
          }
          this.changePage(1, 50)
        }
      },
      deep: true
    },
    apiParams: {
      handler(val, oldValue) {
        if (JSON.stringify(val) !== JSON.stringify(oldValue)) {
          this.localApiParams = val
        }
      },
      immediate: true,
      deep: true
    },
    currentPageRowKeys: {
      handler(val) {
        const self = this
        this.selectedRowKeys = []
        this.selectedRows = []
        const keys = Object.keys(val)
        if (keys.length) {
          keys.map(item => {
            self.selectedRowKeys = [...self.selectedRowKeys, ...val[item]]
            self.selectedRows = [...self.selectedRows, ...self.pageRows[item]]
            this.$emit(
              'change',
              this.selectedRowKeys,
              this.selectedRows,
              this.tableDatas
            )
          })
        } else {
          // this.$emit('change', [], [])
        }
      },
      deep: true,
      immediate: true
    }
  },
  mounted() {
    const self = this
    if (!this.columns?.length) {
      config_list_menu_field_post_(this)
    }
    executeServer(this)
    this.$nextTick(() => {
      self.observeTableHeight()
    })
    window.onresize = () => {
      this.observeTableHeight()
    }
  },
  methods: {
    observeTableHeight() {
      const self = this
      const boxHeight = document.body.offsetHeight
      const node = this.$refs.tableDom?.$el
      node &&
        observeDomResize(node, () => {
          const { top } = node.getBoundingClientRect()
          self.yy = boxHeight - top - 130
        })
    },
    createColumns(datas) {
      const self = this
      this.tableColumns = JSON.parse(JSON.stringify(datas))
      this.tableColumns.forEach(element => {
        element.width = useColumnWidth(element, this)
        if (element?.scopedSlots?.filterDropdown) {
          element.onFilterDropdownVisibleChange = visible => {
            // self.scrollX = self.$refs.tableDom.$el.querySelector('.ant-table-header').scrollLeft
            self.onFilterDropdownVisibleChange(visible, element)
          }
        }
      })
    },
    updateColumnData(key, value, index) {
      this.$set(this.tableColumns[index], key, value)
      this.$forceUpdate()
    },
    changeBatchMode(index, value) {
      this.$set(this.tableColumns[index], 'isBatch', value)
      this.$forceUpdate()
    },
    // 全选
    onCheckAllChange(e, index) {
      const item = this.tableColumns[index]
      item.checkAll = e.target.checked
      item.indeterminate = false
      item.filterValue = e.target.checked
        ? item.plainOptions.map(e => e.key)
        : []
      this.$set(this.tableColumns, index, {
        ...item
      })
    },
    setBlank(e, index) {
      const item = this.tableColumns[index]
      item.isBlank = e.target.checked
      this.$set(this.tableColumns, index, {
        ...item
      })
    },
    // 输入框模糊匹配搜索
    inputSearch: debounce(function (e, index) {
      if (e.target.value) {
        this.tableColumns[index].plainOptions = this.options.filter(
          _ =>
            _.value &&
            _.value.toLowerCase().includes(e.target.value.trim().toLowerCase())
        )
      } else {
        this.tableColumns[index].plainOptions = this.options
      }
    }, 300),
    onChange(checkedList, index) {
      const item = this.tableColumns[index]
      this.tableColumns[index].checkAll =
        checkedList.length === item.plainOptions.length
      this.tableColumns[index].indeterminate =
        !!checkedList.length && checkedList.length < item.plainOptions.length
    },
    onFilterDropdownVisibleChange(visible, item) {
      // const target = this.$refs.tableDom.$el.querySelector('.ant-table-header')
      //

      console.log(this.$refs.tableDom)
      // this.tableDatas.length === 0 && !this.isScrolled
      // setTimeout(() => {
      //   if (this.scrollX > 0) {
      //     target.scrollLeft = this.scrollX
      //     this.isScrolled = true
      //   }
      // }, 500)
      if (visible) {
        item.filtered = true
        this.loading = true
        item.isBatch = false
        if (this.queryFields?.length) {
          item.params.queryFields = this.queryFields
        }
        if (![1].includes(item.model)) {
          getConfigColumn(item, this)
        }
      } else {
        this.scrollX =
          this.$refs.tableDom.$el.querySelector('.ant-table-header').scrollLeft
      }
      item.filtered =
        !!item.filterValue.length ||
        !!item.batchTags?.length ||
        item.desc ||
        item.isBlank
      setTimeout(() => {
        const target =
          this.$refs.tableDom.$el.querySelector('.ant-table-header')
        if (this.scrollX > 0) {
          target.scrollLeft = this.scrollX
        }
      }, 500)
    },
    // 远程搜索
    remoteSearch: debounce(function (e, index) {
      this.loading = true
      const item = this.tableColumns[index]
      item.params.queryStr = e.target.value.trim()
      getConfigColumn(item, this)
    }, 300),

    // 点击搜索
    handleSearch(comfirm, column) {
      this.pageNum = 1
      column.filtered = !!column.filterValue.length
      column.isBatch = false

      comfirm()
      executeSearch(this)
    },
    // 列筛选重置
    handleReset(comfirm, index) {
      this.pageNum = 1
      this.resetColumnFilter(index)
      comfirm()
      executeSearch(this)
    },
    // 排序
    handleSort(sort, index, comfirm) {
      this.tableColumns[index].desc = sort
      comfirm()
      executeSearch(this)
    },
    // 批量查询输入失去焦点
    handlerBatchBlur(e, index) {
      const batchTags = this.tableColumns[index].batchTags
      if (!batchTags) {
        this.tableColumns[index].batchTags = []
      }
      const valueStr = e.target.value.replaceAll(/\t|\n|\s+/g, ' ')
      const values = valueStr.split(' ').filter(item => {
        return item.trim() !== ''
      })
      this.tableColumns[index].batchTags = [
        ...new Set(this.tableColumns[index].batchTags.concat(values))
      ]
      this.tableColumns[index].batchValue = null
    },
    // 删除输入记录
    handlerDelBatchItem(index, columnIndex) {
      this.tableColumns[columnIndex].batchTags.splice(index, 1)
    },
    handleBatchSearch(comfirm, column, isBatch) {
      this.pageNum = 1
      column.filtered = !!column.batchTags?.length
      column.isBatch = true
      comfirm()
      executeSearch(this)
    },
    // 分页
    changePage(page, size) {
      this.pageNum = page
      this.pageSize = size
      executeServer(this)
    },
    // 重置全部清空
    reset() {
      this.pageNum = 1
      this.pageSize = 50
      this.query = { sortList: [] }
      this.clearFilter()
      this.onCancelSelect()
      executeServer(this)
    },
    // 针对搜索条件从外传过来
    toSearch(params) {
      this.pageNum = 1
      this.pageSize = 50
      this.query = params
      this.clearFilter()
      this.onCancelSelect()
      executeServer(this)
    },
    // 重置列条件信息
    resetColumnFilter(index) {
      this.tableColumns[index].filterValue = []
      this.tableColumns[index].indeterminate = false
      this.tableColumns[index].checkAll = false
      this.tableColumns[index].desc = ''
      this.tableColumns[index].filtered = false
      this.tableColumns[index].searchValue = null
      this.tableColumns[index].isBatch = false
      this.tableColumns[index].isBlank = false
      if (this.tableColumns[index].params) {
        this.tableColumns[index].params.queryStr = ''
      }
      this.tableColumns[index].batchTags = []
    },
    clearFilter() {
      this.uid++
      const self = this
      this.tableColumns.forEach((item, index) => {
        self.resetColumnFilter(index)
      })
    },
    // 取消复选框
    onCancelSelect() {
      this.selectedRowKeys = []
      this.currentPageRowKeys = {}
      this.$emit('change', [], [], this.tableDatas)
    },
    onSelectChange(selectedRowKeys, selectedRows) {
      this.$set(this.currentPageRowKeys, this.pageNum, selectedRowKeys)
      this.pageRows[this.pageNum] = selectedRows
    },
    onSelect(record, selected) {
      const index = this.tableDatas.findIndex(item => {
        return item.id === record.id
      })
      this.tableDatas[index].selected = selected

      this.$emit('select', record, selected)
    },
    // 刷新只刷新当前页，保留用户操作的记录
    refresh() {
      this.spinning = true
      executeSearch(this)
    },
    refreshColumn() {
      config_list_menu_field_post_(this)
      executeSearch(this)
    },
    // 导出
    exportExcel() {
      this.$emit(
        'export',
        {
          ...this.apiParams,
          ...this.query
        },
        {
          pageNum: this.pageNum,
          pageSize: this.pageSize
        }
      )
    }
  }
}
</script>
<style lang="less">
.myRemoteTable .ant-table-body {
  min-height: 300px;
}
.myRemoteTable .rm-popover {
  width: 300px;
  max-height: 400px;
  min-height: 200px;
  overflow-y: auto;
}

.tableEmpty .ant-table-empty .ant-table-tbody {
  height: 208px;
}

.tableEmpty .ant-table-empty .ant-table-placeholder {
  // display: none;
  position: absolute;
  width: 100%;
  top: 51px;
  z-index: 5;
}
</style>
